Плохо! Плохо!:  0
Страница 1 из 2 12 ПоследняяПоследняя
Показано с 1 по 10 из 11

Тема: [MV + MZ] SkillDamagePreview

  1. #1
    Бывалый Аватар для Darchan Kaen
    Информация о пользователе
    Регистрация
    17.06.2013
    Адрес
    Одесса
    Сообщений
    851
    Записей в дневнике
    3
    Репутация: 47 Добавить или отнять репутацию

    По умолчанию [MV + MZ] SkillDamagePreview

    Название плагина: DKR_SkillDamagePreview

    Автор: DarchanKaen (основной плагин), Alx_Yago (с версии 5.0), Dmy (с версии 5.0), Yoji Ojima (отображение текста картинкой)

    Версия: 5.0 MV и 3.0 MZ

    Дата выхода:
    Версия 5.0 для MV - 05.11.2021
    Версия 3.0 - 03.06.2021
    Версия 2.0 - 02.06.2021
    Версия 1.0 - 30.05.2021

    Описание плагина:
    Плагин позволяет отображать Урон / Лечение , что будет нанесен по одиночной цели, перед нанесением урона.
    Финальный урон В ЛЮБОМ СЛУЧАЕ (!) будет немного отличаться от конкретного значения.

    Предосмотр урона отображается ТОЛЬКО для скилов с одной фиксированной целью (то есть, не работает для скилов с рандомом выбора цели и атакой всех) не зависимо от количества атак; если атак несколько - выводится суммирующее значение урона.

    Нюансы:
    1. Предосмотр урона отображается ТОЛЬКО для скилов с одной фиксированной целью.
    2. Финальный урон В ЛЮБОМ СЛУЧАЕ (!) будет немного отличаться от конкретного значения.
    3. "Урон" или "Лечение" (слова можно заменить в параметрах плагина) - тип воздействия выводится не из формулы урона, а просто из типа цели: если цель Враг - это всегда "Урона", если цель Союзник - это всегда "Лечение".
    4. При подсчете урона для предосмотра формула выполняется движком - если у вас сложная формула, используйте тег SkillDamagePreviewSimpleFormula (см.ниже)
    5. Номер картинки больше 99 ставить не нужно (!).

    Использование плагина(одинаково и для MV , и для MZ...до версии 5.0, она - только на MV !):

    Параметры:
    В параметрах можно указать: включен ли предосмотр урона по-умолчанию, в каком режиме, номер картинки (задается отображению урона), координаты отображения, а также текста и цвета.
    В версии 5.0 (для MV) в параметрах можно также указать, отображается ли крит.урон, используются ли боевые плагины Yanfly и плагин WeaponSkill, общий текст для всего текста предосмотра Урона, а также доп. сдвиг по оси Y для спец. случаев "особенных" боевок.

    Примечания скила:
    <SkillDamagePreviewSimpleFormula>
    Упрощенная формула урона - для случая, если основная формула как-то влияет на персонажей и ее предварительное исполнение не нужно!
    </SkillDamagePreviewSimpleFormula>
    ИЛИ
    SkillDamagePreviewSKIP - если не нужно, что бы для данного скила отображался предосмотр урона в принципе.
    И (в версии 5.0 для MV)
    <SkillDamagePreviewTextColor>
    n - цифра цвета, аналогичная выделения цвета текстом в сообщениях мейкера (1, 2..., 31 - например), она перекрывает дефолтные настройки плагина.
    </SkillDamagePreviewTextColor>


    Команды:
    (в эвенте, в команде "Скрипт")!

    DKR.SkillDamagePreview.enableSkillDamagePreview(); - включает предосмотр Урона / Лечения.
    DKR.SkillDamagePreview.dissableSkillDamagePreview( ); - отключает предосмотр Урона / Лечения.
    DKR.SkillDamagePreview.changePreviewMode('MODE'); - меняет режим предосмотра Урона / Лечения, где 'MODE' - режим, варианты:

    'RANGE' - показывает мин. и макс. урон (зависит от Разброса скила);
    'VALUE' - показывает конкретное значение урона.

    и только для версии 5.0 на MV:
    DKR.SkillDamagePreview.OnOffGlobalColor(isEnable, globalTextColor); - включить / выключить один цвет для всего текста предосмотра Урона;
    DKR.SkillDamagePreview.OnOffDisplayOnTarget(isEnab le); - показывать текст над целью.
    где
    isEnable - true (да) / false (нет)
    globalTextColor - цвет для всего текста предосмотра Урона.

    Код:
    Спойлер Код плагина, версия 3.0 (старые версии удалены!):



    Спойлер MV, версия 5.0:

    Код:
    /*:
     *-----------------------------------------------------------------------------
     *  DKR SkillDamagePreview
     *-----------------------------------------------------------------------------
     *  For: RPGMAKER MV
     *  DKR_SkillDamagePreview_MV_5.js
     *-----------------------------------------------------------------------------
     *  05.11.2021 - Версия 5.0.0
     *-----------------------------------------------------------------------------
     * Поставляется AS-IS.
     * Вся ответственность при использовании - на Пользователе!
     *-----------------------------------------------------------------------------
     *-----------------------------------------------------------------------------
     * @author DarchanKaen, Alx_Yago, Dmy
     * @target MV
     * @plugindesc (v.5.0.0) Плагин позволяет отображать урон (лечение), что будет нанесен по одиночной цели, перед нанесением урона.
     * @help
     *   DKR SkillDamagePreview MV 5.0
     * ----------------------------------------------------------------------------
     * Благодарности: Alx_Yago и Dmy за помощь в разработке / тестировании плагина
     * ----------------------------------------------------------------------------
     * ----------------------------------------------------------------------------
     * Примечаения!: Корректность работы с другими боевыми плагинами, особенно Yanfly, не гарантируется!
     * ----------------------------------------------------------------------------
     * ---Общая информация:
     * Плагин позволяет отображать урон (лечение), что будет нанесен по одиночной цели, 
     * перед нанесением урона.
     * Финальный урон В ЛЮБОМ СЛУЧАЕ (!) будет немного отличаться 
     * от конкретного значения.
     * ---Использование:
     * --Параметры плагина
     * В параметрах можно указать: включен ли предосмотр урона по-умолчанию, показывать ли крит-й урон,
     * используется ли плагин WeaponSkill, используется ли плагин YanflyBattleCore, используется ли другие
     * боевые плагины Yanfly (для выбора целей, например), использовать ли один и тот же цвет для всего  
     * текста предосмотра, где именно отобажать текст предосмотра, режим предосмотра,
     * номер картинки (задается отображению урона), координаты отображения, а также текста и цвета.
     * --В Примечании скила:
     * <SkillDamagePreviewSimpleFormula>
     *	Упрощенная формула урона - для случая, если основная формула как-то влияет на персонажей
     *  и ее предварительное исполнение не нужно!
     * </SkillDamagePreviewSimpleFormula>
     * <SkillDamagePreviewTextColor>
     *	Принудительное отображение текса предосмотра нужным цветом; цвет указывается числом, полная аналогия с
     *  заданием цвета для фрагмента текста в сообщении, но \C[] писать не нужно - только число.
     * </SkillDamagePreviewTextColor>
     * ИЛИ
     * SkillDamagePreviewSKIP - если не нужно, что бы для данного скила отображался предосмотр урона в принципе.
     * --Команды (для раздела "Скрипт"):
     *	DKR.SkillDamagePreview.enableSkillDamagePreview(); - включает предосмотр Урона / Лечения.
     *	DKR.SkillDamagePreview.dissableSkillDamagePreview(); - отключает предосмотр Урона / Лечения.
     *	DKR.SkillDamagePreview.changePreviewMode('MODE'); - меняет режим предосмотра Урона / Лечения.
     * где 'MODE' - режим, варианты: 
     * 'RANGE' - показывает мин. и макс. урон (зависит от Разброса скила);
     * 'VALUE' - показывает конкретное значение урона.
     * ----------------------------------------------------------------------------
     * 
     * @param skillDamagePreviewOn
     * @type boolean
     * @desc Включен ли предосмотр урона со старта игры.
     * @default true
     * 
     * @param skillIsCritsAffectPreview
     * @type boolean
     * @desc Отображать ли критический урон при предосмотре.
     * @default false
     * 
     * @param skillIsWeaponSkillUsed
     * @type boolean
     * @desc Используется ли плагин WeaponSkill
     * @default false
     * 
     * @param skillIsYanflyBattleCoreUsed
     * @type boolean
     * @desc Используется ли плагин YanflyBattleCore
     * @default false
     * 
     * @param skillIsYanflyWTFUsed
     * @type boolean
     * @desc Используется ли плагины Yanfly WTF
     * @default false
     *
     * @param skillIsOnlyGlobalColor
     * @type boolean
     * @desc Использовать Цветовой код (\C[?]) для ВСЕГО текста предосмотра.
     * @default false
     * 
     * @param skillIsDisplayOnTarget
     * @type boolean
     * @desc Отображать предосмотр Над целью, а не сбоку экрана.
     * @default false
     *
     * @param previewMode
     * @type text
     * @desc Вариант предосмотра урона: или RANGE (мин. и макс. урон) или VALUE (фикс-е значение урона).
     * @default RANGE
     *
     * @param skillDamagePreviewPicNumber
     * @type number
     * @desc Номер картинки, что назначается предосмотру урона.
     * @default 81
     *     
     * @param skillDamagePreviewYOffsetDisplayOnTarget
     * @type number
     * @desc Сдвиг вверх картинки предосмотра урона Над целью.
     * @default 300
     *
     * @param skillDamagePreviewCoordX
     * @type number
     * @desc Координата X картинки предосмотра урона.
     * @default 600
     *     
     * @param skillDamagePreviewCoordY
     * @type number
     * @desc Координата Y картинки предосмотра урона.
     * @default 300
     *     
     * @param enemyDamageWord
     * @type text
     * @desc Текст при выборе скила на Врага.
     * @default Урон
     *     
     * @param allyDamageWord
     * @type text
     * @desc Текст при выборе скила на Союзника.
     * @default Лечение
     *     
     * @param preDamageWord
     * @type text
     * @desc Текст перед значениями урона.
     * @default , ~Σ:
     *     
     * @param betweenMinMaxDamageWord
     * @type text
     * @desc Текст между мин. и макс. уроном.
     * @default ...
      *
     * @param globalColorTag
     * @type number
     * @desc Цветовой код (\C[?]) для ВСЕГО текста .
     * @default 23
     *
     * @param normalColorTag
     * @type number
     * @desc Цветовой код (\C[?]) обычного текста .
     * @default 0
     *
     * @param enemyDamageWordColorTag
     * @type number
     * @desc Цветовой код (\C[?]) обычного текста скила на Врага.
     * @default 10
     *
     * @param allyDamageWordColorTag
     * @type number
     * @desc Цветовой код (\C[?]) обычного текста скила на Союзника.
     * @default 11
     *
     * @param minDamageColorTag
     * @type number
     * @desc Цветовой код (\C[?]) минимального урона.
     * @default 14
     *
     * @param betweenDamageColorTag
     * @type number
     * @desc Цветовой код (\C[?]) текста между мин. и макс. уроном.
     * @default 27
     *
     * @param maxDamageColorTag 
     * @type number
     * @desc Цветовой код (\C[?]) максимального урона.
     * @default 27
     */
     
     
    var Imported = Imported || {};
    Imported.DKR_SkillDamagePreview = true;
    
    var DKR = DKR || {};          
    DKR.SkillDamagePreview = DKR.SkillDamagePreview || {}; 
    DKR.SkillDamagePreview.version = 5.0;
    
    DKR.SkillDamagePreview.parameters = PluginManager.parameters('DKR_SkillDamagePreview_MV_5');
    
    
    ( () => {
    
    	DKR.SkillDamagePreview.skillDamagePreviewOn = (DKR.SkillDamagePreview.parameters['skillDamagePreviewOn']=== 'true') ? true : false;
    	DKR.SkillDamagePreview.previewMode = DKR.SkillDamagePreview.parameters['previewMode'] || 'RANGE';
    	DKR.SkillDamagePreview.skillIsCritsAffectPreview = (DKR.SkillDamagePreview.parameters['skillIsCritsAffectPreview']=== 'true') ? true : false;
    	DKR.SkillDamagePreview.skillIsWeaponSkillUsed = (DKR.SkillDamagePreview.parameters['skillIsWeaponSkillUsed']=== 'true') ? true : false;
    	DKR.SkillDamagePreview.skillIsYanflyBattleCoreUsed = (DKR.SkillDamagePreview.parameters['skillIsYanflyBattleCoreUsed']=== 'true') ? true : false;
    	DKR.SkillDamagePreview.skillIsYanflyWTFUsed = (DKR.SkillDamagePreview.parameters['skillIsYanflyWTFUsed']=== 'true') ? true : false;
    	DKR.SkillDamagePreview.skillIsOnlyGlobalColor = (DKR.SkillDamagePreview.parameters['skillIsOnlyGlobalColor']=== 'true') ? true : false;
    	DKR.SkillDamagePreview.skillIsDisplayOnTarget = (DKR.SkillDamagePreview.parameters['skillIsDisplayOnTarget']=== 'true') ? true : false;
    
    	DKR.SkillDamagePreview.selectedSkill = null;
    	DKR.SkillDamagePreview.isTargetEnemy = true;
    	
    	
    	let skillDamagePreviewPicNumber = Number(DKR.SkillDamagePreview.parameters['skillDamagePreviewPicNumber']) || 81;
    	let skillDamagePreviewYOffsetDisplayOnTarget = Number(DKR.SkillDamagePreview.parameters['skillDamagePreviewYOffsetDisplayOnTarget']) || 300;
    	let skillDamagePreviewCoordX = Number(DKR.SkillDamagePreview.parameters['skillDamagePreviewCoordX']) || 600;
    	let skillDamagePreviewCoordY = Number(DKR.SkillDamagePreview.parameters['skillDamagePreviewCoordY']) || 300;
    	const skillDamagePreviewOrigin = 0;
    	const skillDamagePreviewScaleX = 100;
    	const skillDamagePreviewScaleY = 100;
    	const skillDamagePreviewOpacity = 255;
    	const skillDamagePreviewBlendMode = 0;
    	
    	const defaultAttackSkillId = 1;
    	let textPictureText = '';
    
    	let globalColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['globalColorTag']) + ']' || '\\C[23]';
    	let normalColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['normalColorTag']) + ']' || '\\C[0]';
    	let enemyDamageWordColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['enemyDamageWordColorTag']) + ']' || '\\C[10]';
    	let allyDamageWordColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['allyDamageWordColorTag']) + ']' || '\\C[11]';
    	let minDamageColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['minDamageColorTag']) + ']' || '\\C[14]';
    	let betweenDamageColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['betweenDamageColorTag']) + ']' || '\\C[27]';
    	let maxDamageColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['maxDamageColorTag']) + ']' || '\\C[18]';
    	
    	let enemyDamageWord = DKR.SkillDamagePreview.parameters['enemyDamageWord'] || 'Урон';
    	let allyDamageWord = DKR.SkillDamagePreview.parameters['allyDamageWord'] || 'Лечение';
    	let preDamageWord = DKR.SkillDamagePreview.parameters['preDamageWord'] || ', ~Σ:';
    	let betweenMinMaxDamageWord = DKR.SkillDamagePreview.parameters['betweenMinMaxDamageWord'] || '...';
    	
    	let isSelectedObjectSkill = false;
    
    	let targetCoordX = 0;
        let targetCoordY = 0;
    
    	
    	//-4.0_NEW__GLOBAL TEXT COLOR: begin
    	if(true === DKR.SkillDamagePreview.skillIsOnlyGlobalColor){
    		normalColorTag = '';
    		enemyDamageWordColorTag = '';
    		allyDamageWordColorTag = '';
    		minDamageColorTag = '';
    		betweenDamageColorTag = '';
    		maxDamageColorTag = '';
    	}
    	//-4.0_NEW: end
    
    
    	DKR.SkillDamagePreview.Window_SkillList__UpdateHelp = Window_SkillList.prototype.updateHelp;
    	Window_SkillList.prototype.updateHelp = function(){
    		DKR.SkillDamagePreview.Window_SkillList__UpdateHelp.call(this);
    		
    		if(undefined === this.item()){
    			console.log('DKR.SkillDamagePreview: skill undefined...');
    			return false;
    		}
    		
    		DKR.SkillDamagePreview.selectedSkill = this.item();
    		isSelectedObjectSkill = true;
    	}
    	
    	DKR.SkillDamagePreview.setAttack = Game_Action.prototype.setAttack;
    	Game_Action.prototype.setAttack = function() {
    		DKR.SkillDamagePreview.setAttack.call(this);
    		
    		isSelectedObjectSkill = true;
    		
    		let weaponSkillId = defaultAttackSkillId;
    		
    		if(true === DKR.SkillDamagePreview.skillIsWeaponSkillUsed){
    			let actor = BattleManager.actor();
    			if(false === actor.hasNoWeapons()){
    				let weapon = actor.weapons()[0];
    				try{
    					weaponSkillId = weapon.meta.skill_id;
    				}catch(error){
    					weaponSkillId = defaultAttackSkillId;
    				}
    				if(undefined === weaponSkillId){
    					weaponSkillId = defaultAttackSkillId;
    				}
    			}
    		}
    		
    		DKR.SkillDamagePreview.selectedSkill = $dataSkills[weaponSkillId];
    	};
    
    
    	DKR.SkillDamagePreview.Window_BattleEnemy__select = Window_BattleEnemy.prototype.select;
    	Window_BattleEnemy.prototype.select = function(index){
    		DKR.SkillDamagePreview.Window_BattleEnemy__select.call(this, index);
    		
    			//console.log('---DKR_SELECT: enemy!...this:', this);
    		if(false === DKR.SkillDamagePreview.skillIsYanflyWTFUsed){
    			if(true === DKR.SkillDamagePreview.skillDamagePreviewOn && index > -1){
    				DKR.SkillDamagePreview.isTargetEnemy = true;
    				DKR.SkillDamagePreview.showSkillDamagePreview(index, false);
    			}
    		}else{
    			if(true === DKR.SkillDamagePreview.skillDamagePreviewOn){
    					//console.log('---this.enemy():', this.enemy());
    				if(
    					undefined !== this.enemy() && null !== this.enemy() && 
    					'ALL ALLIES' !== this.enemy() && 'ALL ENEMIES' !== this.enemy() 
    				){
    					
    					if( true === this.enemy().isActor() ){
    						DKR.SkillDamagePreview.isTargetEnemy = false;
    					}else{
    						DKR.SkillDamagePreview.isTargetEnemy = true;
    					}
    					
    					DKR.SkillDamagePreview.showSkillDamagePreview(this.enemy(), true);
    				}
    			}
    		}
    		
    		
    	}
    	
    	DKR.SkillDamagePreview.Window_BattleActor__select = Window_BattleActor.prototype.select;
    	Window_BattleActor.prototype.select = function(index){
    		DKR.SkillDamagePreview.Window_BattleActor__select.call(this, index);
    		
    		
    		if(true === DKR.SkillDamagePreview.skillDamagePreviewOn && index > -1){
    			DKR.SkillDamagePreview.isTargetEnemy = false;
    			DKR.SkillDamagePreview.showSkillDamagePreview(index, false);
    		}
    
    		
    	}
    	
    	
    	DKR.SkillDamagePreview.Window_BattleEnemy__hide = Window_BattleEnemy.prototype.hide;
    	Window_BattleEnemy.prototype.hide = function() {
    		DKR.SkillDamagePreview.Window_BattleEnemy__hide.call(this);
    		
    		$gameScreen.erasePicture(skillDamagePreviewPicNumber);
    		isSelectedObjectSkill = false;
    	};
    	
    	DKR.SkillDamagePreview.Window_BattleActor__hide = Window_BattleActor.prototype.hide;
    	Window_BattleActor.prototype.hide = function() {
    		DKR.SkillDamagePreview.Window_BattleActor__hide.call(this);
    		
    		$gameScreen.erasePicture(skillDamagePreviewPicNumber);
    		isSelectedObjectSkill = false;
    	};
    	
    	DKR.SkillDamagePreview.Scene_Battle__onItemOk = Scene_Battle.prototype.onItemOk;
    	Scene_Battle.prototype.onItemOk = function() {
    		DKR.SkillDamagePreview.Scene_Battle__onItemOk.call(this);
    		
    		$gameScreen.erasePicture(skillDamagePreviewPicNumber);
    		isSelectedObjectSkill = false;
    	};
    	
    	
    	
    	DKR.SkillDamagePreview.showSkillDamagePreview = function(enemyIndex, isYanflyWTFMode){
    		let isTagretPlayer = false;
    		
    		if(false === isSelectedObjectSkill){
    			return false;
    		}
    		
    		let enemy = null;
    		let enemiesTroop = null;
    		
    		if(false === isYanflyWTFMode){
    			if(true === DKR.SkillDamagePreview.isTargetEnemy){
    				if(false === DKR.SkillDamagePreview.skillIsYanflyBattleCoreUsed){
    					enemiesTroop = $gameTroop.aliveMembers();
    				}else{
    					enemiesTroop = $gameTroop.aliveMembers().sort(function(a, b) {
    						if (a.spritePosX() === b.spritePosX()) {
    							return a.spritePosY() - b.spritePosY();
    						}
    						return a.spritePosX() - b.spritePosX();
    					});
    				}
    				
    				
    				if(false === DKR.SkillDamagePreview.skillIsYanflyWTFUsed){
    					enemy = enemiesTroop[enemyIndex];
    				}else{
    					enemy = this.enemy();
    				}
    				
    				
    				
    				//console.log('_ENEMY_INDEX:', enemyIndex);
    				//console.log('_TARGET:', enemy);
    				//console.log('_ENEMIES TROOP:', enemiesTroop);
    				
    				if(enemyIndex >= enemiesTroop.length){
    					console.log('_YANFLY_TARGET_PARADOX !!!');
    					return false;
    				}
    				
    			}else{
    				enemy = $gameParty.members()[enemyIndex];
    				isTagretPlayer = true;
    					//console.log('_TARGET: player');
    			}
    		}else if(true === isYanflyWTFMode){
    
    			if(true === DKR.SkillDamagePreview.isTargetEnemy){
    				enemy = enemyIndex;
    				isTagretPlayer = false;
    			}else{
    				enemy = enemyIndex
    				isTagretPlayer = true;
    			}
    
    		}	
    		
    			//console.log('__DKR.SkillDamagePreview.isTargetEnemy:', DKR.SkillDamagePreview.isTargetEnemy);
    			//console.log('__enemy, isTagretPlayer:', enemy, isTagretPlayer);
    
    		let actor = BattleManager.actor();
    		let skill = DKR.SkillDamagePreview.selectedSkill;
    		
    		if(null === actor){
    			return false;
    		}
    
    		let skillSkipOrSimpleFormula = parseSkillNoteForSOrSF(skill);
    		
    		//-4.0_NEW__SKILL TEXT COLOR: begin
    		let skilltTxtColor = parseSkillNoteForSTC(skill);
    			//console.log('skilltTxtColor:', skilltTxtColor);
    		if('NONE' !== skilltTxtColor){
    			DKR.SkillDamagePreview.OnOffGlobalColor(true, skilltTxtColor);
    		}
    		//-4.0_NEW__SKILL TEXT COLOR: begin
    
    		if('SKIP' === skillSkipOrSimpleFormula){
    			return false;
    		}else if('NONE' === skillSkipOrSimpleFormula){
    			skillSkipOrSimpleFormula = null;
    		}
    		
    		let isSkillCritical = Math.random() < calcIsSkillCritical(enemy, actor, skill);
    		
    		if(false === DKR.SkillDamagePreview.skillIsCritsAffectPreview){
    			isSkillCritical = false;
    		}
    		
    		let totalDamageValue = 0;
    		let currentDamageValue = 0;
    		for(let n = 0; n < skill.repeats; n++){
    			currentDamageValue = makeDamageValue(enemy, actor, skill, isSkillCritical, skillSkipOrSimpleFormula);
    			totalDamageValue += currentDamageValue;
    		}
    		let [minDamage, maxDamage] = getMinMaxDamage(totalDamageValue, skill.damage.variance);
    
    		//-4.0_NEW__DISPLAY ON TARGET: begin
    		if(false === isTagretPlayer && true === DKR.SkillDamagePreview.skillIsDisplayOnTarget){
    			targetCoordX = enemy._screenX;
    			targetCoordY = enemy._screenY - skillDamagePreviewYOffsetDisplayOnTarget;
    			skillDamagePreviewCoordX = targetCoordX;
    			skillDamagePreviewCoordY = targetCoordY;
    		}else{
    			skillDamagePreviewCoordX = Number(DKR.SkillDamagePreview.parameters['skillDamagePreviewCoordX']) || 600;
    			skillDamagePreviewCoordY = Number(DKR.SkillDamagePreview.parameters['skillDamagePreviewCoordY']) || 300;
    		}
    		//-4.0_NEW__DISPLAY ON TARGET: end
    
    		drawSkillDamagePreviewOnEnemy(minDamage, maxDamage);
    		
    		if(true === DKR.SkillDamagePreview.skillIsOnlyGlobalColor){
    			DKR.SkillDamagePreview.OnOffGlobalColor(true);
    		}else{
    			DKR.SkillDamagePreview.OnOffGlobalColor(false);
    		}
    	}	
    	
    	
    	let parseSkillNoteForSOrSF = function(skill){
    		const tag = 'SkillDamagePreviewSimpleFormula';
    		const skipWord = 'SkillDamagePreviewSKIP';
    		
    		let notedata = skill.note.split(/[\r\n]+/);
    		let formulaText = 'NONE';
    
    		if(true === skill.note.includes(skipWord)){
    			formulaText = 'SKIP';
    			return formulaText;
    		}
    
    		let matchCount = 0;
    		for (let i = 0; i < notedata.length; i++) {
    			let line = notedata[i];
    			if (notedata[i].match(tag)) {
    				matchCount++;
    				if(2 === matchCount){
    					break;
    				}else{
    					formulaText = '\r\n';
    					continue;
    				}
    			}
    			if(1 === matchCount){
    				formulaText += notedata[i].trim() + '\r\n'
    			}
    		}
    		
    		return formulaText;
    	}
    	
    	let parseSkillNoteForSTC = function(skill){
    		const tag = 'SkillDamagePreviewTextColor';
    		let skillTextColor = 'NONE';
    
    		let notedata = skill.note.split(/[\r\n]+/);
    		
    		let matchCount = 0;
    		for (let i = 0; i < notedata.length; i++) {
    			let line = notedata[i];
    			if (notedata[i].match(tag)) {
    				matchCount++;
    				if(2 === matchCount){
    					break;
    				}else{
    					skillTextColor = '\r\n';
    					continue;
    				}
    			}
    			if(1 === matchCount){
    				skillTextColor += notedata[i].trim() + '\r\n'
    			}
    		}
    		
    		return skillTextColor;
    	}
    	
    	let getMinMaxDamage = function(damage, variance){
    		let minDamage = 0;
    		let maxDamage = 0;
    		let minMaxDamage = [];
    
    		let diffByVariance = 0;
    		if('RANGE' === DKR.SkillDamagePreview.previewMode){
    			let diffByVariance = Math.round( damage * (variance / 100) );
    			minDamage = Math.round( damage - (diffByVariance + (diffByVariance / 4) ) );
    			maxDamage = Math.round( damage + diffByVariance );
    		}else if('VALUE' === DKR.SkillDamagePreview.previewMode){
    			minDamage = damage;
    			maxDamage = damage;
    		}
    
    		minMaxDamage = [minDamage, maxDamage];
    		
    		return minMaxDamage;
    	}
    
    	
    	let drawSkillDamagePreviewOnEnemy = function(minDamage, maxDamage){
    		let damageTypeWord = '';
    		let damageTypeColorTag = '';
    		if(true === DKR.SkillDamagePreview.isTargetEnemy){
    			damageTypeWord = enemyDamageWord;
    			damageTypeColorTag = enemyDamageWordColorTag;
    		}else{
    			minDamage = Math.abs(minDamage);
    			maxDamage = Math.abs(maxDamage);
    			damageTypeWord = allyDamageWord;
    			damageTypeColorTag = allyDamageWordColorTag;
    		}
    		textPictureText = `${globalColorTag}
    ${damageTypeColorTag}${damageTypeWord}${betweenDamageColorTag}${preDamageWord}
    ${minDamageColorTag}${minDamage}${betweenDamageColorTag}${betweenMinMaxDamageWord}${maxDamageColorTag}${maxDamage}${normalColorTag}`;
    
    		$gameScreen.showPicture(skillDamagePreviewPicNumber, '', skillDamagePreviewOrigin, skillDamagePreviewCoordX, skillDamagePreviewCoordY, skillDamagePreviewScaleX, skillDamagePreviewScaleY, skillDamagePreviewOpacity, skillDamagePreviewBlendMode);
    	}
    
    
    	DKR.SkillDamagePreview.enableSkillDamagePreview = function(){
    		DKR.SkillDamagePreview.skillDamagePreviewOn = true;
    	}
    	
    	DKR.SkillDamagePreview.dissableSkillDamagePreview = function(){
    		DKR.SkillDamagePreview.skillDamagePreviewOn = false;
    	}
    	
    	DKR.SkillDamagePreview.changePreviewMode = function(pMode){
    		DKR.SkillDamagePreview.previewMode = pMode;
    	}
    	
    	DKR.SkillDamagePreview.OnOffGlobalColor = function(isEnable, globalTC = 'NONE'){
    		if('NONE' === globalTC){
    			DKR.SkillDamagePreview.skillIsOnlyGlobalColor = isEnable;
    		}
    		//DKR.SkillDamagePreview.skillIsOnlyGlobalColor = isEnable;
    		if(false === isEnable){
    			globalColorTag = '';
    			normalColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['normalColorTag']) + ']' || '\\C[0]';
    			enemyDamageWordColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['enemyDamageWordColorTag']) + ']' || '\\C[10]';
    			allyDamageWordColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['allyDamageWordColorTag']) + ']' || '\\C[11]';
    			minDamageColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['minDamageColorTag']) + ']' || '\\C[14]';
    			betweenDamageColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['betweenDamageColorTag']) + ']' || '\\C[27]';
    			maxDamageColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['maxDamageColorTag']) + ']' || '\\C[18]';
    		}else{
    			if('NONE' === globalTC){
    				globalColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['globalColorTag']) + ']' || '\\C[23]';
    			}else{
    				globalColorTag = '\\C[' + Number(globalTC) + ']';
    			}
    			normalColorTag = '';
    			enemyDamageWordColorTag = '';
    			allyDamageWordColorTag = '';
    			minDamageColorTag = '';
    			betweenDamageColorTag = '';
    			maxDamageColorTag = '';
    		}
    	}
    
    	DKR.SkillDamagePreview.OnOffDisplayOnTarget = function(isEnable){
    		DKR.SkillDamagePreview.skillIsDisplayOnTarget = isEnable;
    	}
    
    
    	//---COPY PAST CORELIB: BEGIN
    	let makeDamageValue = function(target, actor, skill, isCritical, skillDamageSimpleFormula) {
    		const item = skill;
    		const baseValue = evalDamageFormula(target, actor, skill, skillDamageSimpleFormula);
    		let value = baseValue * calcElementRate(target, actor, skill);
    		
    		if (isPhysical(skill)) {
    			value *= target.pdr;
    		}
    		if (isMagical(skill)) {
    			value *= target.mdr;
    		}
    		if (baseValue < 0) {
    			value *= target.rec;
    		}
    		if (isCritical) {
    			value = applyCritical(value);
    		}
    
    		value = applyVariance(value, item.damage.variance);
    		
    		value = applyGuard(value, target);
    
    		value = Math.round(value);
    		
    		return value;
    	};
    
    	let calcIsSkillCritical = function(target, actor, skill) {
    
    		return skill.damage.critical
    			? actor.cri * (1 - target.cev)
    			: 0;
    
    	};
    
    	let evalDamageFormula = function(target, actor, skill, skillDamageSimpleFormula) {
    		try {
    			
    			let skillDamageFormula = null;
    			if(null === skillDamageSimpleFormula){
    				skillDamageFormula = skill.damage.formula;
    			}else{
    				skillDamageFormula = skillDamageSimpleFormula;
    			}
    			
    			const a = actor; 
    			const b = target; 
    			const v = $gameVariables._data;
    			const sign = [3, 4].includes(skill.damage.type) ? -1 : 1;
    			const value = Math.max(eval(skillDamageFormula), 0) * sign;
    			return isNaN(value) ? 0 : value;
    		} catch (e) {
    			return 0;
    		}
    	};
    
    	let calcElementRate = function(target, actor, skill) {
    		if (skill.damage.elementId < 0) {
    			return elementsMaxRate(target, actor.attackElements());
    		} else {
    			return target.elementRate(skill.damage.elementId);
    		}
    	};
    
    	let elementsMaxRate = function(target, elements) {
    		if (elements.length > 0) {
    			const rates = elements.map(elementId => target.elementRate(elementId));
    			return Math.max(...rates);
    		} else {
    			return 1;
    		}
    	};
    
    	let isPhysical = function(skill) {
    		return skill.hitType === Game_Action.HITTYPE_PHYSICAL;
    	};
    
    	let isMagical = function(skill) {
    		return skill.hitType === Game_Action.HITTYPE_MAGICAL;
    	};
    	
    	let applyCritical = function(damage) {
    		return damage * 3;
    	};
    	
    	let applyVariance = function(damage, variance) {
    		const amp = Math.floor(Math.max((Math.abs(damage) * variance) / 100, 0));
    		const v = Math.randomInt(amp + 1) + Math.randomInt(amp + 1) - amp;
    		return damage >= 0 ? damage + v : damage - v;
    	};
    	
    	let applyGuard = function(damage, target) {
    		return damage / (damage > 0 && target.isGuard() ? 2 * target.grd : 1);
    	};
    	//---COPY PAST CORELIB: END
    	
    	
    	
    	
    	//---Thanks to Yoji Ojima: BEGIN
    	const _Game_Picture_show = Game_Picture.prototype.show;
        Game_Picture.prototype.show = function() {
            _Game_Picture_show.apply(this, arguments);
            if (this._name === "" && textPictureText) {
                this.mzkp_text = textPictureText;
                this.mzkp_textChanged = true;
                textPictureText = '';
            }
        };
    	
    	const _Sprite_Picture_destroy = Sprite_Picture.prototype.destroy;
        Sprite_Picture.prototype.destroy = function() {
            destroyTextPictureBitmap(this.bitmap);
            _Sprite_Picture_destroy.apply(this, arguments);
        };
    
        const _Sprite_Picture_updateBitmap = Sprite_Picture.prototype.updateBitmap;
        Sprite_Picture.prototype.updateBitmap = function() {
            _Sprite_Picture_updateBitmap.apply(this, arguments);
            if (this.visible && this._pictureName === "") {
                const picture = this.picture();
                const text = picture ? picture.mzkp_text || "" : "";
                const textChanged = picture && picture.mzkp_textChanged;
                if (this.mzkp_text !== text || textChanged) {
                    this.mzkp_text = text;
                    destroyTextPictureBitmap(this.bitmap);
                    this.bitmap = createTextPictureBitmap(text);
                    picture.mzkp_textChanged = false;
                }
            } else {
                this.mzkp_text = "";
            }
        };
    
        function createTextPictureBitmap(text) {
            const tempWindow = new Window_Base(new Rectangle());
            const size = {width:750, height: 300}; //MV: hardcode //MZ: textSizeEx(text)
            tempWindow.padding = 0;
            tempWindow.move(0, 0, size.width, size.height);
            tempWindow.createContents();
            tempWindow.drawTextEx(text, 0, 0, 0);
            const bitmap = tempWindow.contents;
            tempWindow.contents = null;
            tempWindow.destroy();
            bitmap.mzkp_isTextPicture = true;
            return bitmap;
        }
    
        function destroyTextPictureBitmap(bitmap) {
            if (bitmap && bitmap.mzkp_isTextPicture) {
                bitmap.clear();
            }
        }
    	//---Thanks to Yoji Ojima: END
    	
    })();


    Спойлер MV, версия 3.0:

    Код:
    /*:
     *-----------------------------------------------------------------------------
     *  DKR SkillDamagePreview
     *-----------------------------------------------------------------------------
     *  For: RPGMAKER MV
     *  DKR_SkillDamagePreview_MV_3.js
     *-----------------------------------------------------------------------------
     *  02.06.2021 - Версия 3.0.0
     *-----------------------------------------------------------------------------
     * Поставляется AS-IS.
     * Вся ответственность при использовании - на Пользователе!
     *-----------------------------------------------------------------------------
     *-----------------------------------------------------------------------------
     * @author DarchanKaen
     * @target MV
     * @plugindesc (v.3.0.0) Плагин позволяет отображать урон (лечение), что будет нанесен по одиночной цели, перед нанесением урона.
     * @help
     *   DKR SkillDamagePreview MV 3.0
     * ----------------------------------------------------------------------------
     * ---Общая информация:
     * Плагин позволяет отображать урон (лечение), что будет нанесен по одиночной цели, 
     * перед нанесением урона.
     * Финальный урон В ЛЮБОМ СЛУЧАЕ (!) будет немного отличаться 
     * от конкретного значения.
     * ---Использование:
     * --Параметры плагина
     * В параметрах можно указать: включен ли предосмотр урона по-умолчанию, в каком режиме,
     *  номер картинки (задается отображению урона), координаты отображения, а также текста и цвета.
     * --В Примечании скила:
     * <SkillDamagePreviewSimpleFormula>
     *	Упрощенная формула урона - для случая, если основная формула как-то влияет на персонажей
     *  и ее предварительное исполнение не нужно!
     * </SkillDamagePreviewSimpleFormula>
     * ИЛИ
     * SkillDamagePreviewSKIP - если не нужно, что бы для данного скила отображался предосмотр урона в принципе.
     * --Команды (для раздела "Скрипт"):
     *	DKR.SkillDamagePreview.enableSkillDamagePreview(); - включает предосмотр Урона / Лечения.
     *	DKR.SkillDamagePreview.dissableSkillDamagePreview(); - отключает предосмотр Урона / Лечения.
     *	DKR.SkillDamagePreview.changePreviewMode('MODE'); - меняет режим предосмотра Урона / Лечения.
     * где 'MODE' - режим, варианты: 
     * 'RANGE' - показывает мин. и макс. урон (зависит от Разброса скила);
     * 'VALUE' - показывает конкретное значение урона.
     * ----------------------------------------------------------------------------
     * ----Версия 5.0 (для MV)
     * Добавлена совместимость с плагинами Yanfly
     * ----------------------------------------------------------------------------
     * 
     * @param skillDamagePreviewOn
     * @type boolean
     * @desc Включен ли предосмотр урона со старта игры.
     * @default true
     * 
     * @param skillIsCritsAffectPreview
     * @type boolean
     * @desc Отображать ли критический урон при предосмотре.
     * @default false
      * 
     * @param skillIsWeaponSkillUsed
     * @type boolean
     * @desc Используется ли плагин WeaponSkill
     * @default false
     *
     * @param previewMode
     * @type text
     * @desc Вариант предосмотра урона: или RANGE (мин. и макс. урон) или VALUE (фикс-е значение урона).
     * @default RANGE
     *
     * @param skillDamagePreviewPicNumber
     * @type number
     * @desc Номер картинки, что назначается предосмотру урона.
     * @default 81
     *     
     * @param skillDamagePreviewCoordX
     * @type number
     * @desc Координата X картинки предосмотра урона.
     * @default 600
     *     
     * @param skillDamagePreviewCoordY
     * @type number
     * @desc Координата Y картинки предосмотра урона.
     * @default 300
     *     
     * @param enemyDamageWord
     * @type text
     * @desc Текст при выборе скила на Врага.
     * @default Урон
     *     
     * @param allyDamageWord
     * @type text
     * @desc Текст при выборе скила на Союзника.
     * @default Лечение
     *     
     * @param preDamageWord
     * @type text
     * @desc Текст перед значениями урона.
     * @default , ~Σ:
     *     
     * @param betweenMinMaxDamageWord
     * @type text
     * @desc Текст между мин. и макс. уроном.
     * @default ...
     *
     * @param normalColorTag
     * @type number
     * @desc Цветовой код (\C[?]) обычного текста .
     * @default 0
     *
     * @param enemyDamageWordColorTag
     * @type number
     * @desc Цветовой код (\C[?]) обычного текста скила на Врага.
     * @default 10
     *
     * @param allyDamageWordColorTag
     * @type number
     * @desc Цветовой код (\C[?]) обычного текста скила на Союзника.
     * @default 11
     *
     * @param minDamageColorTag
     * @type number
     * @desc Цветовой код (\C[?]) минимального урона.
     * @default 14
     *
     * @param betweenDamageColorTag
     * @type number
     * @desc Цветовой код (\C[?]) текста между мин. и макс. уроном.
     * @default 27
     *
     * @param maxDamageColorTag 
     * @type number
     * @desc Цветовой код (\C[?]) максимального урона.
     * @default 27
     */
     
     
    var Imported = Imported || {};
    Imported.DKR_SkillDamagePreview = true;
    
    var DKR = DKR || {};          
    DKR.SkillDamagePreview = DKR.SkillDamagePreview || {}; 
    DKR.SkillDamagePreview.version = 3.0;
    
    DKR.SkillDamagePreview.parameters = PluginManager.parameters('DKR_SkillDamagePreview_MV_3');
    
    
    ( () => {
    
    	DKR.SkillDamagePreview.skillDamagePreviewOn = (DKR.SkillDamagePreview.parameters['skillDamagePreviewOn']=== 'true') ? true : false;
    	DKR.SkillDamagePreview.previewMode = DKR.SkillDamagePreview.parameters['previewMode'] || 'RANGE';
    	DKR.SkillDamagePreview.skillIsCritsAffectPreview = (DKR.SkillDamagePreview.parameters['skillIsCritsAffectPreview']=== 'true') ? true : false;
    	DKR.SkillDamagePreview.skillIsWeaponSkillUsed = (DKR.SkillDamagePreview.parameters['skillIsWeaponSkillUsed']=== 'true') ? true : false;
    
    	DKR.SkillDamagePreview.selectedSkill = null;
    	DKR.SkillDamagePreview.isTargetEnemy = true;
    	
    	
    	let skillDamagePreviewPicNumber = Number(DKR.SkillDamagePreview.parameters['skillDamagePreviewPicNumber']) || 81;
    	let skillDamagePreviewCoordX = Number(DKR.SkillDamagePreview.parameters['skillDamagePreviewCoordX']) || 600;
    	let skillDamagePreviewCoordY = Number(DKR.SkillDamagePreview.parameters['skillDamagePreviewCoordY']) || 300;
    	const skillDamagePreviewOrigin = 0;
    	const skillDamagePreviewScaleX = 100;
    	const skillDamagePreviewScaleY = 100;
    	const skillDamagePreviewOpacity = 255;
    	const skillDamagePreviewBlendMode = 0;
    	
    	const defaultAttackSkillId = 1;
    	let textPictureText = '';
    
    	let normalColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['normalColorTag']) + ']' || '\\C[0]';
    	let enemyDamageWordColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['enemyDamageWordColorTag']) + ']' || '\\C[10]';
    	let allyDamageWordColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['allyDamageWordColorTag']) + ']' || '\\C[11]';
    	let minDamageColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['minDamageColorTag']) + ']' || '\\C[14]';
    	let betweenDamageColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['betweenDamageColorTag']) + ']' || '\\C[27]';
    	let maxDamageColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['maxDamageColorTag']) + ']' || '\\C[18]';
    	
    	let enemyDamageWord = DKR.SkillDamagePreview.parameters['enemyDamageWord'] || 'Урон';
    	let allyDamageWord = DKR.SkillDamagePreview.parameters['allyDamageWord'] || 'Лечение';
    	let preDamageWord = DKR.SkillDamagePreview.parameters['preDamageWord'] || ', ~Σ:';
    	let betweenMinMaxDamageWord = DKR.SkillDamagePreview.parameters['betweenMinMaxDamageWord'] || '...';
    	
    	let isSelectedObjectSkill = false;
    
    
    
    
    	DKR.SkillDamagePreview.Window_SkillList__UpdateHelp = Window_SkillList.prototype.updateHelp;
    	Window_SkillList.prototype.updateHelp = function(){
    		DKR.SkillDamagePreview.Window_SkillList__UpdateHelp.call(this);
    		
    		if(undefined === this.item()){
    			console.log('DKR.SkillDamagePreview: skill undefined...');
    			return false;
    		}
    		
    		DKR.SkillDamagePreview.selectedSkill = this.item();
    		isSelectedObjectSkill = true;
    	}
    	
    	DKR.SkillDamagePreview.setAttack = Game_Action.prototype.setAttack;
    	Game_Action.prototype.setAttack = function() {
    		DKR.SkillDamagePreview.setAttack.call(this);
    		
    		isSelectedObjectSkill = true;
    		
    		let weaponSkillId = defaultAttackSkillId;
    		
    		if(true === DKR.SkillDamagePreview.skillIsWeaponSkillUsed){
    			let actor = BattleManager.actor();
    			if(false === actor.hasNoWeapons()){
    				let weapon = actor.weapons()[0];
    				try{
    					weaponSkillId = weapon.meta.skill_id;
    				}catch(error){
    					weaponSkillId = defaultAttackSkillId;
    				}
    				if(undefined === weaponSkillId){
    					weaponSkillId = defaultAttackSkillId;
    				}
    			}
    		}
    		
    		DKR.SkillDamagePreview.selectedSkill = $dataSkills[weaponSkillId];
    	};
    
    
    	DKR.SkillDamagePreview.Window_BattleEnemy__select = Window_BattleEnemy.prototype.select;
    	Window_BattleEnemy.prototype.select = function(index){
    		DKR.SkillDamagePreview.Window_BattleEnemy__select.call(this, index);
    		
    		if(true === DKR.SkillDamagePreview.skillDamagePreviewOn && index > -1){
    			DKR.SkillDamagePreview.isTargetEnemy = true;
    			DKR.SkillDamagePreview.showSkillDamagePreview(index);
    		}
    	}
    	
    	DKR.SkillDamagePreview.Window_BattleActor__select = Window_BattleActor.prototype.select;
    	Window_BattleActor.prototype.select = function(index){
    		DKR.SkillDamagePreview.Window_BattleActor__select.call(this, index);
    		
    		if(true === DKR.SkillDamagePreview.skillDamagePreviewOn && index > -1){
    			DKR.SkillDamagePreview.isTargetEnemy = false;
    			DKR.SkillDamagePreview.showSkillDamagePreview(index);
    		}
    	}
    	
    	
    	DKR.SkillDamagePreview.Window_BattleEnemy__hide = Window_BattleEnemy.prototype.hide;
    	Window_BattleEnemy.prototype.hide = function() {
    		DKR.SkillDamagePreview.Window_BattleEnemy__hide.call(this);
    		
    		$gameScreen.erasePicture(skillDamagePreviewPicNumber);
    		isSelectedObjectSkill = false;
    	};
    	
    	DKR.SkillDamagePreview.Window_BattleActor__hide = Window_BattleActor.prototype.hide;
    	Window_BattleActor.prototype.hide = function() {
    		DKR.SkillDamagePreview.Window_BattleActor__hide.call(this);
    		
    		$gameScreen.erasePicture(skillDamagePreviewPicNumber);
    		isSelectedObjectSkill = false;
    	};
    	
    	DKR.SkillDamagePreview.Scene_Battle__onItemOk = Scene_Battle.prototype.onItemOk;
    	Scene_Battle.prototype.onItemOk = function() {
    		DKR.SkillDamagePreview.Scene_Battle__onItemOk.call(this);
    		
    		$gameScreen.erasePicture(skillDamagePreviewPicNumber);
    		isSelectedObjectSkill = false;
    	};
    	
    	
    	
    	DKR.SkillDamagePreview.showSkillDamagePreview = function(enemyIndex){
    		if(false === isSelectedObjectSkill){
    			return false;
    		}
    		
    		let enemy = null;
    		let enemiesTroop = null;
    		
    		if(true === DKR.SkillDamagePreview.isTargetEnemy){
    			enemiesTroop = $gameTroop.aliveMembers();
    			enemy = enemiesTroop[enemyIndex];
    		}else{
    			enemy = $gameParty.members()[enemyIndex];
    		}
    	
    		let actor = BattleManager.actor();
    		let skill = DKR.SkillDamagePreview.selectedSkill;
    		
    		if(null === actor){
    			return false;
    		}
    
    		let skillSkipOrSimpleFormula = parseSkillNoteForSOrSF(skill);
    
    		if('SKIP' === skillSkipOrSimpleFormula){
    			return false;
    		}else if('NONE' === skillSkipOrSimpleFormula){
    			skillSkipOrSimpleFormula = null;
    		}
    		
    		let isSkillCritical = Math.random() < calcIsSkillCritical(enemy, actor, skill);
    		
    		if(false === DKR.SkillDamagePreview.skillIsCritsAffectPreview){
    			isSkillCritical = false;
    		}
    		
    		let totalDamageValue = 0;
    		let currentDamageValue = 0;
    		for(let n = 0; n < skill.repeats; n++){
    			currentDamageValue = makeDamageValue(enemy, actor, skill, isSkillCritical, skillSkipOrSimpleFormula);
    			totalDamageValue += currentDamageValue;
    		}
    		let [minDamage, maxDamage] = getMinMaxDamage(totalDamageValue, skill.damage.variance);
    
    		drawSkillDamagePreviewOnEnemy(minDamage, maxDamage);
    	}	
    	
    	
    	let parseSkillNoteForSOrSF = function(skill){
    		const tag = 'SkillDamagePreviewSimpleFormula';
    		const skipWord = 'SkillDamagePreviewSKIP';
    		
    		let notedata = skill.note.split(/[\r\n]+/);
    		let formulaText = 'NONE';
    
    		if(true === skill.note.includes(skipWord)){
    			formulaText = 'SKIP';
    			return formulaText;
    		}
    
    		let matchCount = 0;
    		for (let i = 0; i < notedata.length; i++) {
    			let line = notedata[i];
    			if (notedata[i].match(tag)) {
    				matchCount++;
    				if(2 === matchCount){
    					break;
    				}else{
    					formulaText = '\r\n';
    					continue;
    				}
    			}
    			if(1 === matchCount){
    				formulaText += notedata[i].trim() + '\r\n'
    			}
    		}
    		
    		return formulaText;
    	}
    	
    	
    	let getMinMaxDamage = function(damage, variance){
    		let minDamage = 0;
    		let maxDamage = 0;
    		let minMaxDamage = [];
    
    		let diffByVariance = 0;
    		if('RANGE' === DKR.SkillDamagePreview.previewMode){
    			let diffByVariance = Math.round( damage * (variance / 100) );
    			minDamage = Math.round( damage - (diffByVariance + (diffByVariance / 4) ) );
    			maxDamage = Math.round( damage + diffByVariance );
    		}else if('VALUE' === DKR.SkillDamagePreview.previewMode){
    			minDamage = damage;
    			maxDamage = damage;
    		}
    
    		minMaxDamage = [minDamage, maxDamage];
    		
    		return minMaxDamage;
    	}
    
    	
    	let drawSkillDamagePreviewOnEnemy = function(minDamage, maxDamage){
    		let damageTypeWord = '';
    		let damageTypeColorTag = '';
    		if(true === DKR.SkillDamagePreview.isTargetEnemy){
    			damageTypeWord = enemyDamageWord;
    			damageTypeColorTag = enemyDamageWordColorTag;
    		}else{
    			minDamage = Math.abs(minDamage);
    			maxDamage = Math.abs(maxDamage);
    			damageTypeWord = allyDamageWord;
    			damageTypeColorTag = allyDamageWordColorTag;
    		}
    		textPictureText = `
    ${damageTypeColorTag}${damageTypeWord}${betweenDamageColorTag}${preDamageWord}
    ${minDamageColorTag}${minDamage}${betweenDamageColorTag}${betweenMinMaxDamageWord}${maxDamageColorTag}${maxDamage}${normalColorTag}`;
    
    		$gameScreen.showPicture(skillDamagePreviewPicNumber, '', skillDamagePreviewOrigin, skillDamagePreviewCoordX, skillDamagePreviewCoordY, skillDamagePreviewScaleX, skillDamagePreviewScaleY, skillDamagePreviewOpacity, skillDamagePreviewBlendMode);
    	}
    
    
    	DKR.SkillDamagePreview.enableSkillDamagePreview = function(){
    		DKR.SkillDamagePreview.skillDamagePreviewOn = true;
    	}
    	
    	DKR.SkillDamagePreview.dissableSkillDamagePreview = function(){
    		DKR.SkillDamagePreview.skillDamagePreviewOn = false;
    	}
    	
    	DKR.SkillDamagePreview.changePreviewMode = function(pMode){
    		DKR.SkillDamagePreview.previewMode = pMode;
    	}
    	
    	
    
    
    	//---COPY PAST CORELIB: BEGIN
    	let makeDamageValue = function(target, actor, skill, isCritical, skillDamageSimpleFormula) {
    		const item = skill;
    		const baseValue = evalDamageFormula(target, actor, skill, skillDamageSimpleFormula);
    		let value = baseValue * calcElementRate(target, actor, skill);
    		
    		if (isPhysical(skill)) {
    			value *= target.pdr;
    		}
    		if (isMagical(skill)) {
    			value *= target.mdr;
    		}
    		if (baseValue < 0) {
    			value *= target.rec;
    		}
    		if (isCritical) {
    			value = applyCritical(value);
    		}
    
    		value = applyVariance(value, item.damage.variance);
    		
    		value = applyGuard(value, target);
    
    		value = Math.round(value);
    		
    		return value;
    	};
    
    	let calcIsSkillCritical = function(target, actor, skill) {
    
    		return skill.damage.critical
    			? actor.cri * (1 - target.cev)
    			: 0;
    
    	};
    
    	let evalDamageFormula = function(target, actor, skill, skillDamageSimpleFormula) {
    		try {
    			
    			let skillDamageFormula = null;
    			if(null === skillDamageSimpleFormula){
    				skillDamageFormula = skill.damage.formula;
    			}else{
    				skillDamageFormula = skillDamageSimpleFormula;
    			}
    			
    			const a = actor; 
    			const b = target; 
    			const v = $gameVariables._data;
    			const sign = [3, 4].includes(skill.damage.type) ? -1 : 1;
    			const value = Math.max(eval(skillDamageFormula), 0) * sign;
    			return isNaN(value) ? 0 : value;
    		} catch (e) {
    			return 0;
    		}
    	};
    
    	let calcElementRate = function(target, actor, skill) {
    		if (skill.damage.elementId < 0) {
    			return elementsMaxRate(target, actor.attackElements());
    		} else {
    			return target.elementRate(skill.damage.elementId);
    		}
    	};
    
    	let elementsMaxRate = function(target, elements) {
    		if (elements.length > 0) {
    			const rates = elements.map(elementId => target.elementRate(elementId));
    			return Math.max(...rates);
    		} else {
    			return 1;
    		}
    	};
    
    	let isPhysical = function(skill) {
    		return skill.hitType === Game_Action.HITTYPE_PHYSICAL;
    	};
    
    	let isMagical = function(skill) {
    		return skill.hitType === Game_Action.HITTYPE_MAGICAL;
    	};
    	
    	let applyCritical = function(damage) {
    		return damage * 3;
    	};
    	
    	let applyVariance = function(damage, variance) {
    		const amp = Math.floor(Math.max((Math.abs(damage) * variance) / 100, 0));
    		const v = Math.randomInt(amp + 1) + Math.randomInt(amp + 1) - amp;
    		return damage >= 0 ? damage + v : damage - v;
    	};
    	
    	let applyGuard = function(damage, target) {
    		return damage / (damage > 0 && target.isGuard() ? 2 * target.grd : 1);
    	};
    	//---COPY PAST CORELIB: END
    	
    	
    	
    	
    	//---Thanks to Yoji Ojima: BEGIN
    	const _Game_Picture_show = Game_Picture.prototype.show;
        Game_Picture.prototype.show = function() {
            _Game_Picture_show.apply(this, arguments);
            if (this._name === "" && textPictureText) {
                this.mzkp_text = textPictureText;
                this.mzkp_textChanged = true;
                textPictureText = '';
            }
        };
    	
    	const _Sprite_Picture_destroy = Sprite_Picture.prototype.destroy;
        Sprite_Picture.prototype.destroy = function() {
            destroyTextPictureBitmap(this.bitmap);
            _Sprite_Picture_destroy.apply(this, arguments);
        };
    
        const _Sprite_Picture_updateBitmap = Sprite_Picture.prototype.updateBitmap;
        Sprite_Picture.prototype.updateBitmap = function() {
            _Sprite_Picture_updateBitmap.apply(this, arguments);
            if (this.visible && this._pictureName === "") {
                const picture = this.picture();
                const text = picture ? picture.mzkp_text || "" : "";
                const textChanged = picture && picture.mzkp_textChanged;
                if (this.mzkp_text !== text || textChanged) {
                    this.mzkp_text = text;
                    destroyTextPictureBitmap(this.bitmap);
                    this.bitmap = createTextPictureBitmap(text);
                    picture.mzkp_textChanged = false;
                }
            } else {
                this.mzkp_text = "";
            }
        };
    
        function createTextPictureBitmap(text) {
            const tempWindow = new Window_Base(new Rectangle());
            const size = {width:750, height: 300}; //MV: hardcode //MZ: textSizeEx(text)
            tempWindow.padding = 0;
            tempWindow.move(0, 0, size.width, size.height);
            tempWindow.createContents();
            tempWindow.drawTextEx(text, 0, 0, 0);
            const bitmap = tempWindow.contents;
            tempWindow.contents = null;
            tempWindow.destroy();
            bitmap.mzkp_isTextPicture = true;
            return bitmap;
        }
    
        function destroyTextPictureBitmap(bitmap) {
            if (bitmap && bitmap.mzkp_isTextPicture) {
                bitmap.clear();
            }
        }
    	//---Thanks to Yoji Ojima: END
    	
    })();


    Спойлер MZ, версия 3.0:

    Код:
    /*:
     *-----------------------------------------------------------------------------
     *  DKR SkillDamagePreview
     *-----------------------------------------------------------------------------
     *  For: RPGMAKER MZ
     *  DKR_SkillDamagePreview_MZ_3.0.js
     *-----------------------------------------------------------------------------
     *  02.06.2021 - Версия 3.0.0
     *-----------------------------------------------------------------------------
     * Поставляется AS-IS.
     * Вся ответственность при использовании - на Пользователе!
     *-----------------------------------------------------------------------------
     *-----------------------------------------------------------------------------
     * @author DarchanKaen
     * @target MZ
     * @plugindesc (v.3.0.0) Плагин позволяет отображать урон (лечение), что будет нанесен по одиночной цели, перед нанесением урона.
     * @help
     *   DKR SkillDamagePreview MZ 3.0
     * ----------------------------------------------------------------------------
     * ---Общая информация:
     * Плагин позволяет отображать урон (лечение), что будет нанесен по одиночной цели, 
     * перед нанесением урона.
     * Финальный урон В ЛЮБОМ СЛУЧАЕ (!) будет немного отличаться 
     * от конкретного значения.
     * ---Использование:
     * --Параметры плагина
     * В параметрах можно указать: включен ли предосмотр урона по-умолчанию, в каком режиме,
     *  номер картинки (задается отображению урона), координаты отображения, а также текста и цвета.
     * --В Примечании скила:
     * <SkillDamagePreviewSimpleFormula>
     *	Упрощенная формула урона - для случая, если основная формула как-то влияет на персонажей
     *  и ее предварительное исполнение не нужно!
     * </SkillDamagePreviewSimpleFormula>
     * ИЛИ
     * SkillDamagePreviewSKIP - если не нужно, что бы для данного скила отображался предосмотр урона в принципе.
     * --Команды (для раздела "Скрипт"):
     *	DKR.SkillDamagePreview.enableSkillDamagePreview(); - включает предосмотр Урона / Лечения.
     *	DKR.SkillDamagePreview.dissableSkillDamagePreview(); - отключает предосмотр Урона / Лечения.
     *	DKR.SkillDamagePreview.changePreviewMode('MODE'); - меняет режим предосмотра Урона / Лечения.
     * где 'MODE' - режим, варианты: 
     * 'RANGE' - показывает мин. и макс. урон (зависит от Разброса скила);
     * 'VALUE' - показывает конкретное значение урона.
     * ----------------------------------------------------------------------------
     * ----Версия 3.0.0
     * --Исправлены баги:
     * 1. Баг с невозможностью использовать предметы из-за ошибки.
     * --Новый функционал:
     * 1. Добавлена совместимость с плагином WeaponSkill.
     * --Прочее:
     * 1. В настройках плагина добавлена возможность указать, отображать ли критический урон при предосмотре.
     * 2. В настройках плагина добавлена возможность указать, используется ли плагин WeaponSkill.
     * ----------------------------------------------------------------------------
     * 
     * @param skillDamagePreviewOn
     * @type boolean
     * @desc Включен ли предосмотр урона со старта игры.
     * @default true
     * 
     * @param skillIsCritsAffectPreview
     * @type boolean
     * @desc Отображать ли критический урон при предосмотре.
     * @default false
      * 
     * @param skillIsWeaponSkillUsed
     * @type boolean
     * @desc Используется ли плагин WeaponSkill
     * @default false
     *
     * @param previewMode
     * @type text
     * @desc Вариант предосмотра урона: или RANGE (мин. и макс. урон) или VALUE (фикс-е значение урона).
     * @default RANGE
     *
     * @param skillDamagePreviewPicNumber
     * @type number
     * @desc Номер картинки, что назначается предосмотру урона.
     * @default 81
     *     
     * @param skillDamagePreviewCoordX
     * @type number
     * @desc Координата X картинки предосмотра урона.
     * @default 600
     *     
     * @param skillDamagePreviewCoordY
     * @type number
     * @desc Координата Y картинки предосмотра урона.
     * @default 300
     *     
     * @param enemyDamageWord
     * @type text
     * @desc Текст при выборе скила на Врага.
     * @default Урон
     *     
     * @param allyDamageWord
     * @type text
     * @desc Текст при выборе скила на Союзника.
     * @default Лечение
     *     
     * @param preDamageWord
     * @type text
     * @desc Текст перед значениями урона.
     * @default , ~Σ:
     *     
     * @param betweenMinMaxDamageWord
     * @type text
     * @desc Текст между мин. и макс. уроном.
     * @default ...
     *
     * @param normalColorTag
     * @type number
     * @desc Цветовой код (\C[?]) обычного текста .
     * @default 0
     *
     * @param enemyDamageWordColorTag
     * @type number
     * @desc Цветовой код (\C[?]) обычного текста скила на Врага.
     * @default 10
     *
     * @param allyDamageWordColorTag
     * @type number
     * @desc Цветовой код (\C[?]) обычного текста скила на Союзника.
     * @default 11
     *
     * @param minDamageColorTag
     * @type number
     * @desc Цветовой код (\C[?]) минимального урона.
     * @default 14
     *
     * @param betweenDamageColorTag
     * @type number
     * @desc Цветовой код (\C[?]) текста между мин. и макс. уроном.
     * @default 27
     *
     * @param maxDamageColorTag 
     * @type number
     * @desc Цветовой код (\C[?]) максимального урона.
     * @default 27
     */
     
     
    var Imported = Imported || {};
    Imported.DKR_SkillDamagePreview = true;
    
    var DKR = DKR || {};          
    DKR.SkillDamagePreview = DKR.SkillDamagePreview || {}; 
    DKR.SkillDamagePreview.version = 3.0;
    
    DKR.SkillDamagePreview.parameters = PluginManager.parameters('DKR_SkillDamagePreview_MZ_3.0');
    
    
    ( () => {
    
    	DKR.SkillDamagePreview.skillDamagePreviewOn = (DKR.SkillDamagePreview.parameters['skillDamagePreviewOn']=== 'true') ? true : false;
    	DKR.SkillDamagePreview.previewMode = DKR.SkillDamagePreview.parameters['previewMode'] || 'RANGE';
    	DKR.SkillDamagePreview.skillIsCritsAffectPreview = (DKR.SkillDamagePreview.parameters['skillIsCritsAffectPreview']=== 'true') ? true : false;
    	DKR.SkillDamagePreview.skillIsWeaponSkillUsed = (DKR.SkillDamagePreview.parameters['skillIsWeaponSkillUsed']=== 'true') ? true : false;
    
    	DKR.SkillDamagePreview.selectedSkill = null;
    	DKR.SkillDamagePreview.isTargetEnemy = true;
    	
    	
    	let skillDamagePreviewPicNumber = Number(DKR.SkillDamagePreview.parameters['skillDamagePreviewPicNumber']) || 81;
    	let skillDamagePreviewCoordX = Number(DKR.SkillDamagePreview.parameters['skillDamagePreviewCoordX']) || 600;
    	let skillDamagePreviewCoordY = Number(DKR.SkillDamagePreview.parameters['skillDamagePreviewCoordY']) || 300;
    	const skillDamagePreviewOrigin = 0;
    	const skillDamagePreviewScaleX = 100;
    	const skillDamagePreviewScaleY = 100;
    	const skillDamagePreviewOpacity = 255;
    	const skillDamagePreviewBlendMode = 0;
    	
    	const defaultAttackSkillId = 1;
    	let textPictureText = '';
    
    	let normalColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['normalColorTag']) + ']' || '\\C[0]';
    	let enemyDamageWordColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['enemyDamageWordColorTag']) + ']' || '\\C[10]';
    	let allyDamageWordColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['allyDamageWordColorTag']) + ']' || '\\C[11]';
    	let minDamageColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['minDamageColorTag']) + ']' || '\\C[14]';
    	let betweenDamageColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['betweenDamageColorTag']) + ']' || '\\C[27]';
    	let maxDamageColorTag = '\\C[' + Number(DKR.SkillDamagePreview.parameters['maxDamageColorTag']) + ']' || '\\C[18]';
    	
    	let enemyDamageWord = DKR.SkillDamagePreview.parameters['enemyDamageWord'] || 'Урон';
    	let allyDamageWord = DKR.SkillDamagePreview.parameters['allyDamageWord'] || 'Лечение';
    	let preDamageWord = DKR.SkillDamagePreview.parameters['preDamageWord'] || ', ~Σ:';
    	let betweenMinMaxDamageWord = DKR.SkillDamagePreview.parameters['betweenMinMaxDamageWord'] || '...';
    	
    	let isSelectedObjectSkill = false;
    
    
    
    
    	DKR.SkillDamagePreview.Window_SkillList__UpdateHelp = Window_SkillList.prototype.updateHelp;
    	Window_SkillList.prototype.updateHelp = function(){
    		DKR.SkillDamagePreview.Window_SkillList__UpdateHelp.call(this);
    		
    		if(undefined === this.item()){
    			console.log('DKR.SkillDamagePreview: skill undefined...');
    			return false;
    		}
    		
    		DKR.SkillDamagePreview.selectedSkill = this.item();
    		isSelectedObjectSkill = true;
    	}
    	
    	DKR.SkillDamagePreview.setAttack = Game_Action.prototype.setAttack;
    	Game_Action.prototype.setAttack = function() {
    		DKR.SkillDamagePreview.setAttack.call(this);
    		
    		isSelectedObjectSkill = true;
    		
    		let weaponSkillId = defaultAttackSkillId;
    		
    		if(true === DKR.SkillDamagePreview.skillIsWeaponSkillUsed){
    			let actor = BattleManager._currentActor;
    			if(false === actor.hasNoWeapons()){
    				let weapon = actor.weapons()[0];
    				try{
    					weaponSkillId = weapon.meta.skill_id;
    				}catch(error){
    					weaponSkillId = defaultAttackSkillId;
    				}
    				if(undefined === weaponSkillId){
    					weaponSkillId = defaultAttackSkillId;
    				}
    			}
    		}
    		
    		DKR.SkillDamagePreview.selectedSkill = $dataSkills[weaponSkillId];
    	};
    
    
    	
    	DKR.SkillDamagePreview.Window_BattleEnemy__select = Window_BattleEnemy.prototype.select;
    	Window_BattleEnemy.prototype.select = function(index){
    		DKR.SkillDamagePreview.Window_BattleEnemy__select.call(this, index);
    		
    		if(true === DKR.SkillDamagePreview.skillDamagePreviewOn && index > -1){
    			DKR.SkillDamagePreview.isTargetEnemy = true;
    			DKR.SkillDamagePreview.showSkillDamagePreview(index);
    		}
    	}
    	
    	DKR.SkillDamagePreview.Window_BattleActor__select = Window_BattleActor.prototype.select;
    	Window_BattleActor.prototype.select = function(index){
    		DKR.SkillDamagePreview.Window_BattleActor__select.call(this, index);
    		
    		if(true === DKR.SkillDamagePreview.skillDamagePreviewOn && index > -1){
    			DKR.SkillDamagePreview.isTargetEnemy = false;
    			DKR.SkillDamagePreview.showSkillDamagePreview(index);
    		}
    	}
    	
    	DKR.SkillDamagePreview.Window_BattleEnemy__hide = Window_BattleEnemy.prototype.hide;
    	Window_BattleEnemy.prototype.hide = function() {
    		DKR.SkillDamagePreview.Window_BattleEnemy__hide.call(this);
    		
    		$gameScreen.erasePicture(skillDamagePreviewPicNumber);
    		isSelectedObjectSkill = false;
    	};
    	
    	DKR.SkillDamagePreview.Window_BattleActor__hide = Window_BattleActor.prototype.hide;
    	Window_BattleActor.prototype.hide = function() {
    		DKR.SkillDamagePreview.Window_BattleActor__hide.call(this);
    		
    		$gameScreen.erasePicture(skillDamagePreviewPicNumber);
    		isSelectedObjectSkill = false;
    	};
    	
    	DKR.SkillDamagePreview.Scene_Battle__onItemOk = Scene_Battle.prototype.onItemOk;
    	Scene_Battle.prototype.onItemOk = function() {
    		DKR.SkillDamagePreview.Scene_Battle__onItemOk.call(this);
    		
    		$gameScreen.erasePicture(skillDamagePreviewPicNumber);
    		isSelectedObjectSkill = false;
    	};
    	
    	
    	
    	
    	DKR.SkillDamagePreview.showSkillDamagePreview = function(enemyIndex){
    		if(false === isSelectedObjectSkill){
    			return false;
    		}
    		
    		let enemy = null;
    		let enemiesTroop = null;
    		
    		if(true === DKR.SkillDamagePreview.isTargetEnemy){
    			enemiesTroop = $gameTroop.aliveMembers();
    			enemy = enemiesTroop[enemyIndex];
    		}else{
    			enemy = $gameParty.members()[enemyIndex];
    		}
    	
    		let actor = BattleManager._currentActor;
    		let skill = DKR.SkillDamagePreview.selectedSkill;
    		
    		if(null === actor){
    			return false;
    		}
    
    		let skillSkipOrSimpleFormula = parseSkillNoteForSOrSF(skill);
    
    		if('SKIP' === skillSkipOrSimpleFormula){
    			return false;
    		}else if('NONE' === skillSkipOrSimpleFormula){
    			skillSkipOrSimpleFormula = null;
    		}
    		
    		let isSkillCritical = Math.random() < calcIsSkillCritical(enemy, actor, skill);
    		
    		if(false === DKR.SkillDamagePreview.skillIsCritsAffectPreview){
    			isSkillCritical = false;
    		}
    		
    		let totalDamageValue = 0;
    		let currentDamageValue = 0;
    		for(let n = 0; n < skill.repeats; n++){
    			currentDamageValue = makeDamageValue(enemy, actor, skill, isSkillCritical, skillSkipOrSimpleFormula);
    			totalDamageValue += currentDamageValue;
    		}
    		let [minDamage, maxDamage] = getMinMaxDamage(totalDamageValue, skill.damage.variance);
    
    		drawSkillDamagePreviewOnEnemy(minDamage, maxDamage);
    	}	
    	
    	
    	let parseSkillNoteForSOrSF = function(skill){
    		const tag = 'SkillDamagePreviewSimpleFormula';
    		const skipWord = 'SkillDamagePreviewSKIP';
    		
    		let notedata = skill.note.split(/[\r\n]+/);
    		let formulaText = 'NONE';
    
    		if(true === skill.note.includes(skipWord)){
    			formulaText = 'SKIP';
    			return formulaText;
    		}
    
    		let matchCount = 0;
    		for (let i = 0; i < notedata.length; i++) {
    			let line = notedata[i];
    			if (notedata[i].match(tag)) {
    				matchCount++;
    				if(2 === matchCount){
    					break;
    				}else{
    					formulaText = '\r\n';
    					continue;
    				}
    			}
    			if(1 === matchCount){
    				formulaText += notedata[i].trim() + '\r\n'
    			}
    		}
    		
    		return formulaText;
    	}
    	
    	
    	let getMinMaxDamage = function(damage, variance){
    		let minDamage = 0;
    		let maxDamage = 0;
    		let minMaxDamage = [];
    
    		let diffByVariance = 0;
    		if('RANGE' === DKR.SkillDamagePreview.previewMode){
    			let diffByVariance = Math.round( damage * (variance / 100) );
    			minDamage = Math.round( damage - (diffByVariance + (diffByVariance / 4) ) );
    			maxDamage = Math.round( damage + diffByVariance );
    		}else if('VALUE' === DKR.SkillDamagePreview.previewMode){
    			minDamage = damage;
    			maxDamage = damage;
    		}
    
    		minMaxDamage = [minDamage, maxDamage];
    		
    		return minMaxDamage;
    	}
    
    	
    	let drawSkillDamagePreviewOnEnemy = function(minDamage, maxDamage){
    		let damageTypeWord = '';
    		let damageTypeColorTag = '';
    		if(true === DKR.SkillDamagePreview.isTargetEnemy){
    			damageTypeWord = enemyDamageWord;
    			damageTypeColorTag = enemyDamageWordColorTag;
    		}else{
    			minDamage = Math.abs(minDamage);
    			maxDamage = Math.abs(maxDamage);
    			damageTypeWord = allyDamageWord;
    			damageTypeColorTag = allyDamageWordColorTag;
    		}
    		textPictureText = `
    ${damageTypeColorTag}${damageTypeWord}${betweenDamageColorTag}${preDamageWord}
    ${minDamageColorTag}${minDamage}${betweenDamageColorTag}${betweenMinMaxDamageWord}${maxDamageColorTag}${maxDamage}${normalColorTag}`;
    
    		$gameScreen.showPicture(skillDamagePreviewPicNumber, '', skillDamagePreviewOrigin, skillDamagePreviewCoordX, skillDamagePreviewCoordY, skillDamagePreviewScaleX, skillDamagePreviewScaleY, skillDamagePreviewOpacity, skillDamagePreviewBlendMode);
    	}
    
    
    	DKR.SkillDamagePreview.enableSkillDamagePreview = function(){
    		DKR.SkillDamagePreview.skillDamagePreviewOn = true;
    	}
    	
    	DKR.SkillDamagePreview.dissableSkillDamagePreview = function(){
    		DKR.SkillDamagePreview.skillDamagePreviewOn = false;
    	}
    	
    	DKR.SkillDamagePreview.changePreviewMode = function(pMode){
    		DKR.SkillDamagePreview.previewMode = pMode;
    	}
    	
    	
    
    
    	//---COPY PAST CORELIB: BEGIN
    	let makeDamageValue = function(target, actor, skill, isCritical, skillDamageSimpleFormula) {
    		const item = skill;
    		const baseValue = evalDamageFormula(target, actor, skill, skillDamageSimpleFormula);
    		let value = baseValue * calcElementRate(target, actor, skill);
    		
    		if (isPhysical(skill)) {
    			value *= target.pdr;
    		}
    		if (isMagical(skill)) {
    			value *= target.mdr;
    		}
    		if (baseValue < 0) {
    			value *= target.rec;
    		}
    		if (isCritical) {
    			value = applyCritical(value);
    		}
    
    		value = applyVariance(value, item.damage.variance);
    		
    		value = applyGuard(value, target);
    
    		value = Math.round(value);
    		
    		return value;
    	};
    
    	let calcIsSkillCritical = function(target, actor, skill) {
    		return skill.damage.critical
    			? actor.cri * (1 - target.cev)
    			: 0;
    	};
    
    	let evalDamageFormula = function(target, actor, skill, skillDamageSimpleFormula) {
    		try {
    			
    			let skillDamageFormula = null;
    			if(null === skillDamageSimpleFormula){
    				skillDamageFormula = skill.damage.formula;
    			}else{
    				skillDamageFormula = skillDamageSimpleFormula;
    			}
    			
    			const a = actor; 
    			const b = target; 
    			const v = $gameVariables._data;
    			const sign = [3, 4].includes(skill.damage.type) ? -1 : 1;
    			const value = Math.max(eval(skillDamageFormula), 0) * sign;
    			return isNaN(value) ? 0 : value;
    		} catch (e) {
    			return 0;
    		}
    	};
    
    	let calcElementRate = function(target, actor, skill) {
    		if (skill.damage.elementId < 0) {
    			return elementsMaxRate(target, actor.attackElements());
    		} else {
    			return target.elementRate(skill.damage.elementId);
    		}
    	};
    
    	let elementsMaxRate = function(target, elements) {
    		if (elements.length > 0) {
    			const rates = elements.map(elementId => target.elementRate(elementId));
    			return Math.max(...rates);
    		} else {
    			return 1;
    		}
    	};
    
    	let isPhysical = function(skill) {
    		return skill.hitType === Game_Action.HITTYPE_PHYSICAL;
    	};
    
    	let isMagical = function(skill) {
    		return skill.hitType === Game_Action.HITTYPE_MAGICAL;
    	};
    	
    	let applyCritical = function(damage) {
    		return damage * 3;
    	};
    	
    	let applyVariance = function(damage, variance) {
    		const amp = Math.floor(Math.max((Math.abs(damage) * variance) / 100, 0));
    		const v = Math.randomInt(amp + 1) + Math.randomInt(amp + 1) - amp;
    		return damage >= 0 ? damage + v : damage - v;
    	};
    	
    	let applyGuard = function(damage, target) {
    		return damage / (damage > 0 && target.isGuard() ? 2 * target.grd : 1);
    	};
    	//---COPY PAST CORELIB: END
    	
    	
    	
    	
    	//---Thanks to Yoji Ojima: BEGIN
    	const _Game_Picture_show = Game_Picture.prototype.show;
        Game_Picture.prototype.show = function() {
            _Game_Picture_show.apply(this, arguments);
            if (this._name === "" && textPictureText) {
                this.mzkp_text = textPictureText;
                this.mzkp_textChanged = true;
                textPictureText = '';
            }
        };
    	
    	const _Sprite_Picture_destroy = Sprite_Picture.prototype.destroy;
        Sprite_Picture.prototype.destroy = function() {
            destroyTextPictureBitmap(this.bitmap);
            _Sprite_Picture_destroy.apply(this, arguments);
        };
    
        const _Sprite_Picture_updateBitmap = Sprite_Picture.prototype.updateBitmap;
        Sprite_Picture.prototype.updateBitmap = function() {
            _Sprite_Picture_updateBitmap.apply(this, arguments);
            if (this.visible && this._pictureName === "") {
                const picture = this.picture();
                const text = picture ? picture.mzkp_text || "" : "";
                const textChanged = picture && picture.mzkp_textChanged;
                if (this.mzkp_text !== text || textChanged) {
                    this.mzkp_text = text;
                    destroyTextPictureBitmap(this.bitmap);
                    this.bitmap = createTextPictureBitmap(text);
                    picture.mzkp_textChanged = false;
                }
            } else {
                this.mzkp_text = "";
            }
        };
    
        function createTextPictureBitmap(text) {
            const tempWindow = new Window_Base(new Rectangle());
            const size = tempWindow.textSizeEx(text);
            tempWindow.padding = 0;
            tempWindow.move(0, 0, size.width, size.height);
            tempWindow.createContents();
            tempWindow.drawTextEx(text, 0, 0, 0);
            const bitmap = tempWindow.contents;
            tempWindow.contents = null;
            tempWindow.destroy();
            bitmap.mzkp_isTextPicture = true;
            return bitmap;
        }
    
        function destroyTextPictureBitmap(bitmap) {
            if (bitmap && bitmap.mzkp_isTextPicture) {
                bitmap.destroy();
            }
        }
    	//---Thanks to Yoji Ojima: END
    
    	
    })();






    Скриншоты:
    Спойлер Как это выглядит в игре:
    MV, лечение Союзника, режим 'VALUE'


    MZ, атакующий скил на Врага, режим 'RANGE'


    MZ, атакующий скил на Врага, режим 'VALUE', кастомная настройка координат-цвета-текста




    Изменения
    Спойлер Версия 5.0:
    Изменения в Версии 5.0
    Добавлена доп. совместимость с боевыми плагинами Yanfly, улучшена совместимость с плагином WeaponSkill, добавлена возможность в скилле указывать принудительный цвет текста. Введены новые параметры плагина.

    Спойлер Версия 3.0:
    Изменения в Версии 3.0
    Исправлены баги:
    1. Баг с невозможностью использовать предметы из-за ошибки.
    Новый функционал:
    1. Добавлена совместимость с плагином WeaponSkill.
    Прочее:
    1. В настройках плагина добавлена возможность указать, отображать ли критический урон при предосмотре (по-умолчанию: отключено).
    2. В настройках плагина добавлена возможность указать, используется ли плагин WeaponSkill (по-умолчанию: отключено).

    Спойлер Версия 2.0:
    Изменения в Версии 2.0
    Исправлены баги:
    1. Баг с автоматическим выбором мертвого Врага как цели для случаев, если противников несколько.
    2. Баг с не удалением текста лечения Союзника в случае отмены скила.
    Новый функционал:
    1. Возможность в Примечании скила прописать в теге SkillDamagePreviewSimpleFormula формулу урона - в этом случае
    для предосмотра урона для данного скила будет использована именно эта формула вместо формулы самого скила.
    2. Возможность в Примечании скила прописать SkillDamagePreviewSKIP для отмены предосмотра урона для данного скила.
    Прочее:
    1. Добавлена возможность настройки плагина при помощи параметров (цвета, текста, координаты).



    Загрузка:
    Спойлер Ссылки на загрузку, версия 5.0(только MV) и (3.0 (Старые версии удалены!):


    Условия поставки плагина:
    Поставляется AS-IS.
    Вся ответственность при использовании - на Пользователе!
    !

    Совместимость с другими плагинами Авторы не гарантируют (однако, с плагинами DKR_PictureOnSkillObserve и WeaponSkill данный плагин совместим...с версии плагина 3.0). С версии 5.0 повышена совместимость с боевыми плагинами Yanfly, но полная совместимость все еще не гарантируется !

    Спойлер Лирическое отступление:
    Странно, что такой плагин никто не сделал...ну или я плохо гуглил.
    Всего-то перетащить из кор-либы самого мейкера функцию подсчета урона (и все зависимые функции).
    Создание окон я все еще не освоил и текст, опять, отображается картинкой.
    ...И оказалось, что у GALVа есть похожий плагин, вот это прикол. =)


    Благодарности:
    Alx_Yago - за помощь в создании версии 5.0, идею плагина и помощь в поиске багов.
    Dmy - за помощь в создании версии 5.0.
    Yoji Ojima - за технику отображения текста картинкой.
    Последний раз редактировалось Darchan Kaen; 19.12.2021 в 18:14. Причина: Выход версии плагина 5.0

  2. #2

    По умолчанию

    Оно работает! Но есть несколько моментов, которые было бы здорово поправить:

    Иногда плагин показывает урон в разы больше обычного, полагаю, это связано с тем, что у него в момент подсчёта выпадает крит.

    У меня есть навык, где в формуле урона прописана потеря ХП для атакующего (такой удар с откатом по себе). Плагин при подсчёте сразу вычитает это ХП у героя, а также вычитает его при каждой смене цели. Так же работают и навыки, где в формуле урона прописаны бафы/дебафы/состояния и всё такое прочее. Тут я вижу решение в том, чтобы писать упрощённую формулу в комментарии к навыку и дать плагину возможность брать её оттуда.

    Классно было бы вывести настройки цветов, надписей и расположения в настройки плагина.

  3. #3
    Бывалый Аватар для Darchan Kaen
    Информация о пользователе
    Регистрация
    17.06.2013
    Адрес
    Одесса
    Сообщений
    851
    Записей в дневнике
    3
    Репутация: 47 Добавить или отнять репутацию

    По умолчанию

    Цитата Сообщение от Alx_Yago Посмотреть сообщение
    Оно работает! Но есть несколько моментов, которые было бы здорово поправить:

    Иногда плагин показывает урон в разы больше обычного, полагаю, это связано с тем, что у него в момент подсчёта выпадает крит.

    У меня есть навык, где в формуле урона прописана потеря ХП для атакующего (такой удар с откатом по себе). Плагин при подсчёте сразу вычитает это ХП у героя, а также вычитает его при каждой смене цели. Так же работают и навыки, где в формуле урона прописаны бафы/дебафы/состояния и всё такое прочее. Тут я вижу решение в том, чтобы писать упрощённую формулу в комментарии к навыку и дать плагину возможность брать её оттуда.

    Классно было бы вывести настройки цветов, надписей и расположения в настройки плагина.
    Хмм, насчет формулы не уверен, но посмотрю что можно сделать.
    С настройками у меня пока туговато - на данный момент могу сделать вызовом скрипта:
    1. Для установки новых координат отображения урона и задания номера картинки.
    2. Для задания цветов.
    3. Для задания текстов.
    Спойлер В принципе, это все редактируется в самом файле плагина:
    Параметры картинки: номер, координаты расположения, и.т.д.:
    const skillDamagePreviewPicNumber = 81;
    const skillDamagePreviewOrigin = 0;
    const skillDamagePreviewCoordX = 600;
    const skillDamagePreviewCoordY = 300;
    const skillDamagePreviewScaleX = 100;
    const skillDamagePreviewScaleY = 100;
    const skillDamagePreviewOpacity = 255;
    const skillDamagePreviewBlendMode = 0;
    Цвета текста:
    const normalColorTag = '\\C[0]';
    const enemyDamageWordColorTag = '\\C[10]';
    const allyDamageWordColorTag = '\\C[11]';
    const minDamageColorTag = '\\C[14]';
    const betweenDamageColorTag = '\\C[27]';
    const maxDamageColorTag = '\\C[18]';
    Текст в зависимости от типа цели (Враг / Союзник):
    const enemyDamageWord = 'Урон';
    const allyDamageWord = 'Лечение';

    Также в функции drawSkillDamagePreviewOnEnemy , в textPictureText = `` можно изменить знак между мин. и макс. уроном и убрать символ суммы.

    Неудобно, конечно...но если очень нужно.


  4. #4

    По умолчанию

    Хоть я вообще не умею писать плагины, но да, найти и заменить коды для цвета могу.
    Я даже нашёл уже, как брать формулу из примечаний к навыку: заменить строчку
    Код:
    const value = Math.max(eval(item.damage.formula), 0) * sign;
    на
    Код:
    const value = Math.max(eval(item.meta.dampreview), 0) * sign;
    и в комментарии к навыку писать <dampreview: формула>

    Правда в таком виде перестаёт правильно отображаться лечение. Плагин считает его за нанесение урона.

    Но вот что ещё заметил!
    При убийстве врага сбивается нумерация противников, и плагин начинает брать для подсчёта данные с уже умерших врагов, подставляя их к живым.

    А вообще я чем дальше, тем больше хочу приспособить этот плагин для своей игры. Мне кажется, он будет прям очень полезным.

  5. #5
    Бывалый Аватар для Darchan Kaen
    Информация о пользователе
    Регистрация
    17.06.2013
    Адрес
    Одесса
    Сообщений
    851
    Записей в дневнике
    3
    Репутация: 47 Добавить или отнять репутацию

    По умолчанию

    Обновил плагин до версии 2.0.

    Изменения в Версии 2.0:
    Исправлены баги:
    1. Баг с автоматическим выбором мертвого Врага как цели для случаев, если противников несколько.
    2. Баг с не удалением текста лечения Союзника в случае отмены скила.
    Новый функционал:
    1. Возможность в Примечании скила прописать в теге SkillDamagePreviewSimpleFormula формулу урона - в этом случае
    для предосмотра урона для данного скила будет использована именно эта формула вместо формулы самого скила.
    2. Возможность в Примечании скила прописать SkillDamagePreviewSKIP для отмены предосмотра урона для данного скила.
    Прочее:
    1. Добавлена возможность настройки плагина при помощи параметров (цвета, текста, координаты).

    Подробности в топик-старте.

  6. #6

    По умолчанию

    Плагин всё лучше и лучше! Мне даже неловко находить в нём новые проблемные места

    У меня он по-прежнему не понимает лечения и считает его за нанесение урона (и даже пишет с отрицательными значениями). Но это бог с ним, можно и вовсе отключить отображение.

    Также, как выяснилось, плагин не понимает использование предметов (вроде лечащих бутылочек), и подставляет вместо них чёрте что, а то и вовсе выдаёт ошибку.

    Ещё он, к сожалению, не взаимодействует с коробочным плагином WeaponSkill, который позволяет прикрутить к оружию особую атаку вместо базовой. Он так и продолжает брать формулу обычной атаки, судя по всему.

    Зато я нашёл, как избавиться от высчитывания критического урона, подредактировав строчку:
    Код:
    let calcIsSkillCritical = function(target, actor, skill) {
    		return skill.damage.critical
    			? actor.cri * (1 - target.cev)
    			: 0;
    Но вообще спасибо, что ты решил его сделать! Я уже вот-вот собираюсь выложить демо Гильдии, и он там будет очень к месту.

  7. #7
    Бывалый Аватар для Darchan Kaen
    Информация о пользователе
    Регистрация
    17.06.2013
    Адрес
    Одесса
    Сообщений
    851
    Записей в дневнике
    3
    Репутация: 47 Добавить или отнять репутацию

    По умолчанию

    Цитата Сообщение от Alx_Yago Посмотреть сообщение
    Плагин всё лучше и лучше! Мне даже неловко находить в нём новые проблемные места

    У меня он по-прежнему не понимает лечения и считает его за нанесение урона (и даже пишет с отрицательными значениями). Но это бог с ним, можно и вовсе отключить отображение.

    Также, как выяснилось, плагин не понимает использование предметов (вроде лечащих бутылочек), и подставляет вместо них чёрте что, а то и вовсе выдаёт ошибку.

    Ещё он, к сожалению, не взаимодействует с коробочным плагином WeaponSkill, который позволяет прикрутить к оружию особую атаку вместо базовой. Он так и продолжает брать формулу обычной атаки, судя по всему.

    Зато я нашёл, как избавиться от высчитывания критического урона, подредактировав строчку:
    Код:
    let calcIsSkillCritical = function(target, actor, skill) {
    		return skill.damage.critical
    			? actor.cri * (1 - target.cev)
    			: 0;
    Но вообще спасибо, что ты решил его сделать! Я уже вот-вот собираюсь выложить демо Гильдии, и он там будет очень к месту.
    Спасибо.
    Вопросы:
    1. Мейкер MV ?
    2. Скилл лечение какой-то хитрой формулой?
    При лечении Союзника не может отображаться минус - в коде для Союзника берётся модуль для среза минуса...
    Нужен пример с твоей стороны - лучше всего скрин Скила лечения и что в бою видно.
    3. Избавиться от вы считывания Крит. Урона - он рассчитывается неверно или нужно что бы он не рассчитывался в принципе или для отдельного Скила?

    Да, плагин не для предметов. По идее он никак не должен с ними взаимодействовать... Проверю этот момент дополнительно.
    Есть мысль как подружить с WeaponSkill, но проверить смогу только вечером.

  8. #8

    По умолчанию

    1. Мейкер MV
    2. Скилл лечения без выкрутасов:
    Спойлер скрины:




    3. Крит урон вообще не должен учитываться в предварительном вычислении. А то иногда он выпадает, и плагин показывает увеличенный урон, а при нанесении выходит обычный, и цифры, получается, расходятся.

    С предметами, я так понял, сейчас ситуация такая, что если предмет можно применить в бою, и надо указывать для него цель, то плагин берёт формулу из последнего применённого навыка. А если до этого никакой навык не применялся, просто выдаёт ошибку.

  9. #9
    Бывалый Аватар для Darchan Kaen
    Информация о пользователе
    Регистрация
    17.06.2013
    Адрес
    Одесса
    Сообщений
    851
    Записей в дневнике
    3
    Репутация: 47 Добавить или отнять репутацию

    По умолчанию

    Цитата Сообщение от Alx_Yago Посмотреть сообщение
    1. Мейкер MV
    2. Скилл лечения без выкрутасов:
    Спойлер скрины:




    3. Крит урон вообще не должен учитываться в предварительном вычислении. А то иногда он выпадает, и плагин показывает увеличенный урон, а при нанесении выходит обычный, и цифры, получается, расходятся.

    С предметами, я так понял, сейчас ситуация такая, что если предмет можно применить в бою, и надо указывать для него цель, то плагин берёт формулу из последнего применённого навыка. А если до этого никакой навык не применялся, просто выдаёт ошибку.
    Я так и не смог проявить баг с лечением, ни в MV , ни в MZ.
    Ты не менял код плагина относительно расчета мин. и макс. урона или вывода текста с информацией?
    Проверь в версии 3.0.

    Обновил плагин до версии 3.0.

    Изменения в Версии 3.0
    Исправлены баги:
    1. Баг с невозможностью использовать предметы из-за ошибки.
    Новый функционал:
    1. Добавлена совместимость с плагином WeaponSkill.
    Прочее:
    1. В настройках плагина добавлена возможность указать, отображать ли критический урон при предосмотре (по-умолчанию: отключено).
    2. В настройках плагина добавлена возможность указать, используется ли плагин WeaponSkill (по-умолчанию: отключено).

    Если вы скачивали более старые версии - в них есть критический баг при выборе предметов в бою. =(
    Используйте данную версию.

    P.S:
    за исключением ремонта багов, в ближайшее время (вероятно, до конца лета) плагин дорабатываться не будет.
    Последний раз редактировалось Darchan Kaen; 19.12.2021 в 18:21.

  10. #10

    По умолчанию

    Спасибо, похоже, всё, что надо, работает!

    С лечением у меня возникали конфликты из-за плагина YEP_X_SelectionControl как оказалось.
    Но ничего страшного: сейчас для меня это не принципиальная функция.

Страница 1 из 2 12 ПоследняяПоследняя

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Метки этой темы

Социальные закладки

Социальные закладки

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •  
[MV + MZ] SkillDamagePreview